#ifndef __tenacitas_log__level__h__
#define __tenacitas_log__level__h__


// =============================================================================
/** @file */

// =============================================================================
/** todo */

// =============================================================================
//                                 C++ Headers
#include <cstdint>
#include <string>

// =============================================================================
//                                 3rds Headers

#include <boost/thread/thread.hpp>
// =============================================================================
//                                 Our Headers
#include <tenacitas_exception/exception.h>

// =============================================================================
//                                 Namespaces
using namespace std;


// =============================================================================
//                                 Macro Contants
/** */


// =============================================================================
//                                 Macro Commands
/** */


/** namespace of the organization */
namespace tenacitas {
    /** namespace for the project */
    namespace log {

        // =========================== Typedefs ===========================

        // ============================ Pre-Declarations ==================

        // ============================ Attributes ========================
        /** */
        

        // ============================ Functions =========================
        /** */
        int64_t th2int( boost::thread::id p_id );
        
        // ============================ Classes ===========================

        /** Levels for logging messages

         There are 6 levels of logging defined: trace, debug, info, warn, error
         and critical. @p trace is the lowest and @p critical is the highest
         level

         <b>A word to the programmer user</b>
         You should use the tenacitas::log::level::trace,
         tenacitas::log::level::debug, tenacitas::log::level::info,
         tenacitas::log::level::warn, tenacitas::log::level::error or
         tenacitas::log::level::critical objects to define the log level
         you want to use.
            @nosubgrouping 
        */
        class level {

        public:

            // --- level - Public Internal Types ------------------------

            /** Type for the internal level of the log */
            typedef int16_t value;


            // --- level - Public Constructors --------------------------

            /** Copy constructor */
            level( const level & p_level )
            : m_value( p_level.m_value ) {}
            

            /** Destructor */
            ~level( ) {}
            

            // --- level - Public Accessors -----------------------------

            /** Informs a string corresponding a log level object */
            std::string str( ) const {
                if ( m_value == trace.val( ) ) { return "trace"; }
                if ( m_value == debug.val( ) ) { return "debug"; }
                if ( m_value == info.val( ) ) { return "info"; }
                if ( m_value == warn.val( ) ) { return "warn"; }
                if ( m_value == error.val( ) ) { return "error"; }
                if ( m_value == critical.val( ) ) { return "critical"; }

                // this is just to make the compiler happy
                return "INVALID-LOG-LEVEL";
            }

            // --- level - Public Processors ----------------------------

            /** Creates a log level object based on a string */
            static const level & create( const std::string & p_str ) {
                if ( p_str == "trace" ) { return trace; }
                if ( p_str == "debug" ) { return debug; }
                if ( p_str == "info" ) { return info; }
                if ( p_str == "warn" ) { return warn; }
                if ( p_str == "error" ) { return error; }
                if ( p_str == "critical" ) { return critical; }

                std::stringstream l_stream;
                l_stream << "'" << p_str << "' is an invalid string for a "
                    "'tenacitas::log::level' value";
                
                tenacitas::exception::exception
                    l_ex( make_tenacitas_exception( l_stream.str( ) ) ); 
                throw ( l_ex );
            }


            // --- level - Public Operators -----------------------------

            /** Returns the corresponding numeric value for a log level */
            value val( ) const {
                return m_value;
            }
            

            /** assignment */
            level & operator = ( const level & p_level ) {
                if ( this != & p_level ) {
                    m_value = p_level.m_value;
                }
                return *this;
            }

            /** equal-to */
            bool operator == ( const level & p_level ) const {
                return m_value == p_level.m_value;
            }

            /** not-equal-to */
            bool operator != ( const level & p_level ) const {
                return m_value != p_level.m_value;
            }

            /** greater-than-or-equal-to */
            bool operator >= ( const level & p_level ) const {
                return m_value >= p_level.m_value;
            }

            /** greater-than not allowed */
            bool operator > ( const level & ) const = delete;

            /** less-than-or-equal-to */
            bool operator <= ( const level & p_level ) const {
                return m_value <= p_level.m_value;
            }

            /** less-than not allowed */
            bool operator < ( const level & ) const = delete;

            // --- level - Public Attributes ----------------------------

            /** Only posssibe log level values - trace */
            static const level trace;

            /** Only posssibe log level values - debug */
            static const level debug;

            /** Only posssibe log level values - info */
            static const level info;

            /** Only posssibe log level values - warn */
            static const level warn;

            /** Only posssibe log level values - error */
            static const level error;

            /** Only posssibe log level values - critical */
            static const level critical;

        private:
            // --- level - Private Constructors -------------------------

            /** Constructor */
            level( value p_value )
            : m_value( p_value ) {
            }

            // --- level - Private Attributes ---------------------------

            /** numerica value for a log level */
            value m_value;
        };
    }
}

// =============================================================================
//                     I M P L E M E N T A T I O N
// =============================================================================

using namespace tenacitas::log;



#endif
